package tech.xs.sys.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import tech.xs.common.framework.domain.annotations.AuthApi;
import tech.xs.common.framework.domain.entity.BaseEntity;
import tech.xs.common.framework.domain.model.ApiResult;
import tech.xs.common.framework.domain.model.PageResult;
import tech.xs.common.sys.domain.constant.PermissionConstant;
import tech.xs.sys.domain.bo.role.EditRoleBo;
import tech.xs.sys.domain.bo.role.PageRoleBo;
import tech.xs.sys.domain.entity.SysRole;
import tech.xs.sys.service.SysRolePermissionService;
import tech.xs.sys.service.SysRoleService;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;

@Slf4j
@Validated
@RestController
@RequestMapping("/role")
public class SysRoleController {

    @Resource
    private SysRoleService sysRoleService;
    @Resource
    private SysRolePermissionService sysRolePermissionService;

    /**
     * 根据id更新或保存角色信息
     *
     * @param bo 请求数据
     * @return 响应数据
     * @author 沈家文
     * @since 2023/6/21 16:10
     */
    @PostMapping("/saveOrUpdate")
    @AuthApi(permissions = PermissionConstant.ROLE_MGR)
    public ApiResult<SysRole> manualEdit(@Validated @RequestBody EditRoleBo bo) {
        long existCount = sysRoleService.count(Wrappers.<SysRole>lambdaQuery()
                .eq(SysRole::getCode, bo.getCode())
                .ne(bo.getId() != null, BaseEntity::getId, bo.getId()));
        if (existCount > 0) {
            return ApiResult.error("角色编码已经存在");
        }

        SysRole saveData = new SysRole();
        BeanUtil.copyProperties(bo, saveData);
        if (bo.getId() != null) {
            SysRole dbData = sysRoleService.getOne(Wrappers.<SysRole>lambdaQuery().eq(BaseEntity::getId, bo.getId()));
            if (dbData == null) {
                return ApiResult.error("根据id在系统中未查询到数据");
            }
            if (!dbData.getCode().equals(bo.getCode()) && sysRoleService.isUsed(dbData.getCode())) {
                return ApiResult.error("角色编码已经被使用,不允许修改");
            }
            if (dbData.getCode().equals(bo.getCode()) && !dbData.getRoleStatus().equals(bo.getRoleStatus())) {
                sysRoleService.deleteEnableRoleCache();
                sysRolePermissionService.deleteEnableRolePermissionCache();
            }
        }

        log.info("更新或保存角色:" + saveData);
        sysRoleService.saveOrUpdate(saveData);
        return ApiResult.success(saveData);
    }


    /**
     * 根据角色编码删除角色
     * <p>
     * 1.删除角色权限管理表数据
     * 2.删除角色数据
     *
     * @param roleCode 角色编码
     * @return 响应数据
     * @author 沈家文
     * @since 2023/7/11 16:42
     */
    @DeleteMapping("/delete/code")
    @AuthApi(permissions = PermissionConstant.ROLE_MGR)
    public ApiResult<String> deleteByCode(@RequestParam String roleCode) {
        if (StrUtil.isBlank(roleCode)) {
            return ApiResult.error("[roleCode]不能为空");
        }
        long count = sysRoleService.count(Wrappers.<SysRole>lambdaQuery().eq(SysRole::getCode, roleCode));
        if (count <= 0) {
            return ApiResult.error("角色不存在或已删除:" + roleCode);
        }
        if (sysRoleService.isUsed(roleCode)) {
            return ApiResult.error("角色编码已经被使用,不允许删除");
        }
        log.info("手动删除角色:" + roleCode);
        sysRoleService.deleteRoleByCode(roleCode);
        return ApiResult.success(roleCode);
    }

    @GetMapping("/list/page")
    @AuthApi(permissions = PermissionConstant.ROLE_MGR)
    public PageResult<SysRole> page(@ModelAttribute PageRoleBo bo) {
        return PageResult.success(sysRoleService.page(bo.page(), bo.query()));
    }

    /**
     * 查询全部角色列表
     *
     * @return 根据查询条件检索出的全部角色列表
     * @author 沈家文
     * @since 2023/9/20 16:52
     */
    @GetMapping("/list/all")
    @AuthApi(permissions = {PermissionConstant.USER_EDIT})
    public ApiResult<List<SysRole>> listAll() {
        return ApiResult.success(sysRoleService.list(Wrappers.<SysRole>lambdaQuery()
                .orderByAsc(SysRole::getCode)));
    }

    @PostMapping("/loadEnableRole")
    public ApiResult<Set<String>> loadRoleAllPermission(@RequestBody Set<String> roles) {
        return ApiResult.success(sysRoleService.loadEnableRoleCache(roles));
    }

}
